#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<getopt.h>
#include<netdb.h>
#include<dirent.h>
#include<signal.h>
#include<syslog.h>
#include<time.h>
#include<libgen.h>
#include<syslog.h>
#include<pthread.h>
#include<ctype.h>
 
#define ip_len       32
int                  g_stop=0;
typedef void *(THREAD_BODY) (void *thread_arg);
 
void dns(char *domain_name,char **ip);
void sig_handler(int signum);
int getdatatime(char *DATATIME);
int ds18b20_get_temperature(float *temp);
int thread_start(pthread_t *thread_id,THREAD_BODY *thread_workbody,void *thread_arg); 
void *thread_worker(void *ctx);
 
void dns(char *domain_name,char **ip)
{
   struct hostent       *server_name=NULL;
 
   server_name=gethostbyname(domain_name);
   inet_ntop(server_name->h_addrtype,server_name->h_addr,*ip,32);
}
 
void sig_handler(int signum)
{
  if(SIGTERM==signum)
  {
     printf("SIGTERM signal detected\n");
     g_stop=1;
  }
  else if(SIGALRM==signum)
  {
     printf("SIGALRM signal detected\n");
     g_stop=1;
  }
  else if(SIGINT==signum)
  {
     printf("SIGINT signal detected\n");
     g_stop=1;
  }
}
 
int getdatatime(char *DATATIME)
{
  time_t seconds;
  struct tm *pTM;
  
  time(&seconds);
  pTM=localtime(&seconds);
  sprintf(DATATIME,"%04d-%02d-%02d  %02d:%02d:%02d\n",pTM->tm_year+1900,pTM->tm_mon+1,pTM->tm_mday,pTM->tm_hour,pTM->tm_min,pTM->tm_sec);
  return 0; 
}
 
int ds18b20_get_temperature(float *temp)
{
        char     w1_path[50]="/sys/bus/w1/devices/";
        char     chip[20];
        char     buf[128];
        DIR      *dirp;
        struct dirent  *direntp;
        int   fd=-1;
        char   *ptr;
        int    found=0;
  
  if(!temp)
  {
    return -1;
  }
  if((dirp=opendir(w1_path))==NULL)
  {
    printf("opendir error:%s\n",strerror(errno));
    return -2;
  }
  while((direntp=readdir(dirp))!=NULL)
  {
    if(strstr(direntp->d_name,"28-"))
    {
      strcpy(chip,direntp->d_name);
      found=1;
      break;
    }
  }
  closedir(dirp);
  if(!found)
  {
    printf("can not find bs18b20 in %s\n",w1_path);
    return -3;
  }
    strncat(w1_path,chip,sizeof(w1_path)-strlen(w1_path));
    strncat(w1_path,"/w1_slave",sizeof(w1_path)-strlen(w1_path));
    if((fd=open(w1_path,O_RDONLY))<0)
    {
      printf("open %s error:%s\n",w1_path,strerror(errno));
      return -4;
    }
    if(read(fd,buf,sizeof(buf))<0)
    {
      printf("read %s error:%s\n",w1_path,strerror(errno));
      return -5;
    }
    ptr=strstr(buf,"t=");
    if(!ptr)
    {
      printf("error:can not get temperature\n");
      return -6;
    }
    ptr+=2;
    *temp=atof(ptr)/1000.0;
    close(fd);
    return 0;
}
 
int thread_start(pthread_t *thread_id,THREAD_BODY *thread_workbody,void *thread_arg)
{
  int                      rv=-1;
  pthread_attr_t           thread_attr;
 
       if(pthread_attr_init(&thread_attr))
       {
                 printf("pthread_attr_init()failure:%s\n",strerror(errno)); 
                 pthread_attr_destroy(&thread_attr);
       }
        
       if(pthread_attr_setstacksize(&thread_attr,120*1024))
       {
                 printf("pthread_attr_setstacksize()failure:%s\n",strerror(errno));
                 pthread_attr_destroy(&thread_attr);
       } 
       if(pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED))
       {
                 printf("pthread_attr_setdatachstate()failure:%s\n",strerror(errno));
                 pthread_attr_destroy(&thread_attr);
       }
       if(pthread_create(thread_id,&thread_attr,thread_workbody,thread_arg))
       {
                 printf("create thread failure:%s\n",strerror(errno));
                 pthread_attr_destroy(&thread_attr);
       }
             rv=0;
             return rv;
}
 
void *thread_worker(void *ctx)
{
        int         clifd;
        int         rv;
        char        buf[1024];
        int         i;
         
            clifd=(int)ctx;
            printf("child thread start to communicate with socket client...\n");
         while(!g_stop)
          { 
            memset(buf,0,sizeof(buf));
            rv=read(clifd,buf,sizeof(buf));
            if(rv<0)
            {
                    printf("read data from server by server[%d] failure:%s\n",clifd,strerror(errno));
                    close(clifd);
                    pthread_exit(NULL);
            }
            else if(rv==0)
            {
                 printf("server_fd [%d] get disconnect\n",clifd);
                 close(clifd);
                 pthread_exit(NULL);
            }
            {
                printf("read %d bytes data from server:%s\n",rv,buf);
            }
              rv=write(clifd,buf,rv);
            if(rv<0)
            {
                    printf("write to server by server_fd [%d] failure:%s\n",clifd,strerror(errno));
                    close(clifd);
                    pthread_exit(NULL);
            }
                    printf("write to server by server_fd[%d] [%s]successfully!\n",clifd,buf);
      }
}
int main(int argc,char **argv)
{
        int                    opt=-1;
        int                    server_fd=-1;
        int                    rv=-1;
        int                    port;
        char                   buf[256];
        float                  temp; 
        char                   datatime[32]; 
        struct sockaddr_in     servaddr;
        struct sockaddr_in     cliaddr;
        char                   *servip=(char *)malloc(ip_len);
        char                   *user="liushoujin";
        char                   *progname=basename(argv[0]);
        int                    clifd=-1;
        int                    on=1;
	int                    log_fd=-1;
        socklen_t              len;
        pthread_t              tid;     
  
        opt=getopt(argc,argv,"xy");
        if(opt!='x' && opt!='y')
        {
            printf("argument parsing failure:%s\n",strerror(errno));
            return -1;
        }
        if(opt=='x')
        {
            dns("master.iot-yun.com",&servip);
        }
        if(opt=='y')
        {
            dns("studio.iot-yun.com",&servip);
        }
        server_fd = socket( AF_INET, SOCK_STREAM, 0);
            if(server_fd < 0)
        {
            printf("Fail to create a client socket [%d]: %s\n", server_fd, strerror(errno) );
                return -1;
        }
            printf("creat a client socket[%d] successufully!\n",server_fd);
             memset(&servaddr, 0, sizeof(servaddr));
             servaddr.sin_family = AF_INET;
             if(opt == 'x')
             {
             servaddr.sin_port = htons(port=9033);
             printf("Get temperature from [%d]master.iot-yun.com...\n",port);
             }
             if(opt == 'y')
             {
             servaddr.sin_port =htons(port=8034);
             printf("Get temperature form studio.iot-yun.com...\n");
             }
             servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
             signal(SIGTERM,sig_handler);
             signal(SIGALRM,sig_handler);
             signal(SIGINT,sig_handler);
     
             setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
             rv=bind(server_fd,(struct sockaddr *)&servaddr,sizeof(servaddr));
             if(rv<0)
             {
                  printf("socket[%d] bind on port[%d] failure:%s\n",server_fd,port,strerror(errno));
                  return -1;
             }
             listen(server_fd,13);
             printf("start to listen port[%d]\n",port);
             
	     log_fd = open("temper.log",O_CREAT|O_RDWR, 0666);
	     if (log_fd < 0)
	     {
		     printf("Open the logfile failure : %s\n", strerror(errno));
		     return 0;
	     }
	       
	     dup2(log_fd, STDOUT_FILENO);
	     dup2(log_fd, STDERR_FILENO); 
	     
	     if ((daemon(1, 1)) < 0)
	     {
		     printf("Deamon failure : %s\n", strerror(errno));
		     return 0;
	     }
              
             while(!g_stop)
             {
                 getdatatime(datatime);
                 ds18b20_get_temperature(&temp);
                 snprintf(buf,sizeof(buf),"%s/%s/%f",user,datatime,temp);
                 clifd=accept(server_fd,(struct sockaddr *)&cliaddr,&len);
               if(clifd<0) 
               { 
                  printf("accept new client failure:%s\n",strerror(errno));
                  continue;
               }
                  printf("accept new clent[%s:%d] successfully!\n",inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port));
                 thread_start(&tid,thread_worker,(void *)clifd);
            
             }
                 syslog(LOG_NOTICE,"program %s stop running...\n",progname);
                 closelog();
                 close(clifd);
}           
